package com.hzw.saas.service.group.service;

import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Resource;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzw.saas.api.group.IGroupMemberRoleRefService;
import com.hzw.saas.api.group.IGroupMemberService;
import com.hzw.saas.api.group.IGroupService;
import com.hzw.saas.api.group.bo.GroupBo;
import com.hzw.saas.api.group.bo.GroupMemberBo;
import com.hzw.saas.api.group.bo.UserMemberBo;
import com.hzw.saas.common.config.util.AssertUtil;
import com.hzw.saas.common.util.IdWorker;
import com.hzw.saas.service.group.mapper.GroupMemberMapper;
import com.hzw.saas.service.group.model.GroupMember;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import jodd.util.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;

/**
 * <p>
 * 群组成员表 服务实现类
 * </p>
 *
 * @author sonam
 * @since 2020-12-23
 */
@Slf4j
@RequiredArgsConstructor
@Service("groupMemberServiceImpl")
public class GroupMemberServiceImpl extends ServiceImpl<GroupMemberMapper, GroupMember> implements IGroupMemberService, IService<GroupMember> {
    @Resource(name = "groupMemberRoleRefServiceImpl")
    private IGroupMemberRoleRefService memberRoleRefService;
    @Resource(name = "groupServiceImpl")
    private IGroupService groupService;

    private final GroupMemberMapper groupMemberMapper;
    private final IdWorker idWorker;
    private final MapperFacade mapperFacade;

    @Override
    public List<String> getGroupIdListByUserId(String userId) {
        List<String> groupIds = new ArrayList<>();

        List<GroupMember> groupMembers = groupMemberMapper.selectList(Wrappers.<GroupMember>lambdaQuery()
            .select(GroupMember::getGroupId)
            .eq(GroupMember::getUserId, userId));
        groupMembers.forEach(groupMember -> {
            groupIds.add(groupMember.getGroupId());
        });

        return groupIds;
    }

    @Override
    public List<String> getAllMemberUserIdByGroupId(String groupId) {
        if(StringUtil.isBlank(groupId)) {
            return new ArrayList<>();
        }

        List<GroupMember> groupMembers = groupMemberMapper.selectList(Wrappers.<GroupMember>lambdaQuery()
            .select(GroupMember::getUserId)
            .eq(GroupMember::getGroupId, groupId));
        List<String> userIds = groupMembers.stream().map(GroupMember::getUserId).collect(Collectors.toList());
        return userIds;
    }

    @Override
    public IPage<UserMemberBo> getGroupUserAndRoleList(String groupId, Page<UserMemberBo> page) {
        IPage<UserMemberBo> memberRoleDtoPage = groupMemberMapper.getGroupUserAndRoleList(groupId, page);
        return memberRoleDtoPage;
    }

    @Override
    public GroupMemberBo getById(String memberId) {
        GroupMember groupMember = groupMemberMapper.selectById(memberId);
        return mapperFacade.map(groupMember, GroupMemberBo.class);
    }

    @Override
    public boolean tryJoinGroup(String userId, String groupId) {
        GroupBo groupBo = groupService.getGroupById(groupId);
        if (StringUtil.isBlank(groupBo.getOwnerId())) {
            return true;
        }

        return count(Wrappers.<GroupMember>lambdaQuery()
            .eq(GroupMember::getGroupId, groupId)
            .eq(GroupMember::getUserId, userId)) > 0;
    }

    @Override
    public int getMemberCountByGroupId(String groupId) {
        return count(Wrappers.<GroupMember>lambdaQuery().eq(GroupMember::getGroupId, groupId));
    }

    @Override
    public Map<String, List<String>> getAllByIds(List<String> groupIds) {
        if (CollectionUtil.isEmpty(groupIds)){
            return Collections.emptyMap();
        }
        List<GroupMember> list = this.lambdaQuery().in(GroupMember::getGroupId,groupIds).list();
        if (CollectionUtil.isNotEmpty(list)){
            HashMap<String, List<String>> stringListHashMap = new HashMap<>();
            Map<String, List<GroupMember>> collect = list.stream().collect(Collectors.groupingBy(GroupMember::getGroupId));
            collect.forEach((s, groupMembers) -> {
                ArrayList<String> stringArrayList = new ArrayList<>();
                if (CollectionUtil.isNotEmpty(groupMembers)){
                    List<String> collect1 = groupMembers.stream().map(GroupMember::getUserId).collect(Collectors.toList());
                    stringArrayList.addAll(collect1);
                }
                stringListHashMap.put(s,stringArrayList);
            });
            return stringListHashMap;
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean memberJoinGroup(String groupId, String userId, String roleId) {
        // 判断用户是否加入
        AssertUtil.assertThrow("用户已加入该群组", tryJoinGroup(userId, groupId));

        // 加入用户
        GroupMember groupMember = new GroupMember();
        groupMember.setMemberId(String.valueOf(idWorker.nextId()));
        groupMember.setUserId(userId);
        groupMember.setGroupId(groupId);
        groupMember.setJoinDate(new Date());
        groupMemberMapper.insert(groupMember);

        memberRoleRefService.addMemberRole(groupMember.getMemberId(), roleId);
        return true;
    }

}
